#include "BitStream.h"

bool CBitStream::get_header(uint32 *headerstring,enum e_syncmode syncmode)
{
	bool result = true, sync;

	if ( !res )
		return 0;

	do
	{
		// Read 4 bytes from the file
		if (res->read(headerstring,4) != 4)
			return false;

#ifdef DAMN_INTEL_BYTE_ORDER
		if (syncmode == INITIAL_SYNC)
		{
			sync = ((*headerstring & 0x0000F0FF) == 0x0000F0FF);
		}
		else
		{
   			sync = ((*headerstring & 0x000CF8FF) == syncword) && (((*headerstring & 0xC0000000) == 0xC0000000) == single_ch_mode);
		}
#else
		if (syncmode == INITIAL_SYNC)
		{
			sync = ((*headerstring & 0xFFF00000) == 0xFFF00000);
		}
		else
		{
			sync = ((*headerstring & 0xFFF80C00) == syncword) && (((*headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
		}
#endif // DAMN_INTEL_BYTE_ORDER

		// rewind 3 bytes in the file so we can try to sync again, if successful set result to true
		if (!sync)
		{
			result = (res->skip(-3) != 0);
		}
	} while (!sync && result);

	if (!result)
		return false;

#ifdef DAMN_INTEL_BYTE_ORDER
	uint32 header = *headerstring;
	*headerstring = swap_int32(header);
#endif

	current_frame_number++;

	return true;
}

static uint32 bitmask[18] =
{
	0,	// dummy
	0x00000001, 0x00000003, 0x00000007, 0x0000000F,
	0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
	0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
	0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
	0x0001FFFF
};

uint32 CBitStream::get_bits(uint32 number_of_bits)
{
	uint32 returnvalue;
	uint32 sum = bitindex + number_of_bits;

	if (sum <= 32)
	{
		// all bits contained in *wordpointer
		returnvalue = (*wordpointer >> (32 - sum)) & bitmask[number_of_bits];
		if ((bitindex += number_of_bits) == 32)
		{
			bitindex = 0;
			wordpointer++;
		}
		return returnvalue;
	}

#ifdef DAMN_INTEL_BYTE_ORDER
	*((int16*)&returnvalue + 1) = *(int16*)wordpointer;
	wordpointer++;
	*(int16*)&returnvalue = *((int16*)wordpointer + 1);
#else
	*(int16*)&returnvalue = *((int16*)wordpointer + 1);
	wordpointer++;
	*((int16*)&returnvalue + 1) = *(int16*)wordpointer;
#endif

	returnvalue >>= 48 - sum;	// returnvalue >>= 16 - (number_of_bits - (32 - bitindex))
	returnvalue &= bitmask[number_of_bits];
	bitindex = sum - 32;

	return returnvalue;
}
